/*
 *  KeyLok.cpp
 *
 *  Created by Pat Long (plong0) on 08/04/09.
 *  Copyright 2009 Tangible Interaction Inc. All rights reserved.
 *
 */

#include "KeyLok.h"

KeyLok::KeyLok(){
	this->ReturnValue1 = this->ReturnValue2 = 0;
	this->setValidateCodes(0, 0, 0);
	this->setClientIDCodes(0, 0);
	this->setReadCodes(0, 0, 0);
	this->setWriteCodes(0, 0, 0);
}

KeyLok::~KeyLok(){
}

/** This routine makes the security system call. */
void KeyLok::KTASK(unsigned CommandCode, unsigned Argument2, unsigned Argument3, unsigned Argument4){
	unsigned long int ReturnValue;
	ReturnValue = KFUNC(CommandCode, Argument2, Argument3, Argument4);
	this->ReturnValue1 = (unsigned) (ReturnValue & 0XFFFF);
	this->ReturnValue2 = (unsigned) (ReturnValue >> 16);
}

/** This function rotates the bits in the Target left the number of positions
 identified by the argument Counts */
unsigned KeyLok::RotateLeft(unsigned Target, int Counts){
	int i;
	static unsigned LocalTarget, HighBit;
	
	LocalTarget = Target;
	for (i=0; i<Counts; i++)
	{
		HighBit = LocalTarget & 0X8000;
		LocalTarget = (LocalTarget << 1) + (HighBit >> 15);
	}
	LocalTarget = LocalTarget & 0XFFFF; /* For 32 bit integers */
	return (LocalTarget);
}


bool KeyLok::isConnected(){
	bool connected = false;

	this->KTASK((unsigned)(KLCHECK), this->validateCode1, this->validateCode2, this->validateCode3);
	this->KTASK(RotateLeft(this->ReturnValue1, this->ReturnValue2 & 7) ^ this->readCode3 ^ this->ReturnValue2,
		  RotateLeft(this->ReturnValue2, this->ReturnValue1 & 15),
		  this->ReturnValue1 ^ this->ReturnValue2, 0);

	// NOTE: Higher security can be achieved by using return values in
	//       computations and performing comparison of computed values to
	//       expected values deeper in your code than here.
	if ((this->ReturnValue1 == this->clientIDCode1) && (this->ReturnValue2 == this->clientIDCode2))
		connected = true;
	else
		connected = false;
	return connected;
}

void KeyLok::setValidateCode(int validateCode, int codeNum){
	if(codeNum == 1)
		this->validateCode1 = validateCode;
	else if(codeNum == 2)
		this->validateCode2 = validateCode;
	else if(codeNum == 3)
		this->validateCode3 = validateCode;
	else
		cout << "Unknown validate code number:" << codeNum << endl;
}

void KeyLok::setValidateCodes(int validateCode1, int validateCode2, int validateCode3){
	this->setValidateCode(validateCode1, 1);
	this->setValidateCode(validateCode2, 2);
	this->setValidateCode(validateCode3, 3);
}

void KeyLok::setClientIDCode(int clientIDCode, int codeNum){
	if(codeNum == 1)
		this->clientIDCode1 = clientIDCode;
	else if(codeNum == 2)
		this->clientIDCode2 = clientIDCode;
	else
		cout << "Unknown clientID code number:" << codeNum << endl;
}

void KeyLok::setClientIDCodes(int clientIDCode1, int clientIDCode2){
	this->setClientIDCode(clientIDCode1, 1);
	this->setClientIDCode(clientIDCode2, 2);
}

void KeyLok::setReadCode(int readCode, int codeNum){
	if(codeNum == 1)
		this->readCode1 = readCode;
	else if(codeNum == 2)
		this->readCode2 = readCode;
	else if(codeNum == 3)
		this->readCode3 = readCode;
	else
		cout << "Unknown read code number:" << codeNum << endl;
}

void KeyLok::setReadCodes(int readCode1, int readCode2, int readCode3){
	this->setReadCode(readCode1, 1);
	this->setReadCode(readCode2, 2);
	this->setReadCode(readCode3, 3);
}

void KeyLok::setWriteCode(int writeCode, int codeNum){
	if(codeNum == 1)
		this->writeCode1 = writeCode;
	else if(codeNum == 2)
		this->writeCode2 = writeCode;
	else if(codeNum == 3)
		this->writeCode3 = writeCode;
	else
		cout << "Unknown write code number:" << codeNum << endl;
}

void KeyLok::setWriteCodes(int writeCode1, int writeCode2, int writeCode3){
	this->setWriteCode(writeCode1, 1);
	this->setWriteCode(writeCode2, 2);
	this->setWriteCode(writeCode3, 3);
}
